using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using SeataNet.Core.AT;
using SeataNet.Core.Configuration;
using SeataNet.Core.Context;
using SeataNet.Core.Exceptions;
using SeataNet.Core.Interceptors;
using SeataNet.Core.Protocol;
using SeataNet.Core.RPC;
using System.Collections.Concurrent;
using System.Reflection;

namespace SeataNet.Core.DependencyInjection
{
    /// <summary>
    /// AT模式服务扩展
    ///
    /// 提供ASP.NET Core依赖注入的扩展方法，用于注册AT模式的所有服务。
    ///
    /// 职责：
    /// 1. 注册AT模式核心服务（事务管理器、数据源代理工厂等）
    /// 2. 注册AT模式配置（重试次数、锁策略等）
    /// 3. 注册AT模式拦截器和切面
    /// 4. 注册AT模式数据源代理
    ///
    /// 使用场景：
    /// ```csharp
    /// // Startup.cs或Program.cs中配置服务
    /// services.AddAtMode(options =>
    /// {
    ///     options.ReportRetryCount = 5;
    ///     options.LockRetryTimes = 30;
    ///     options.TransactionTablePrefix = "undo_log";
    /// });
    ///
    /// // 添加数据源
    /// services.AddAtDataSource(
    ///     connectionString: "Server=...;Database=...",
    ///     providerName: "Microsoft.Data.SqlClient"
    /// );
    /// ```
    ///
    /// 服务注册顺序：
    /// 1. AddSeata()：注册Seata核心服务（RPC、上下文等）
    /// 2. AddAtMode()：注册AT模式服务
    /// 3. AddAtDataSource()：注册AT数据源代理
    ///
    /// 注意事项：
    /// - 扩展方法用于IServiceCollection，简化配置
    /// - 所有服务默认注册为Singleton生命周期
    /// - 配置使用Options模式，支持热更新
    /// - 必须先注册Seata核心服务才能使用AT模式
    /// </summary>
    public static class AtServiceCollectionExtensions
    {
        /// <summary>
        /// 添加AT模式服务（使用默认配置）
        ///
        /// 注册AT模式的所有核心服务到依赖注入容器。
        ///
        /// 执行流程：
        /// 1. 注册IAtTransactionManager → DefaultAtTransactionManager（Singleton）
        ///    - AT事务管理器，负责分支注册、状态上报、回滚等
        /// 2. 注册IAtDataSourceProxyFactory → DefaultAtDataSourceProxyFactory（Singleton）
        ///    - 数据源代理工厂，负责创建和缓存AtDataSourceProxy
        /// 3. 注册IMethodInterceptor → AtTransactionInterceptor（Singleton）
        ///    - AT事务拦截器，用于AOP拦截标记[GlobalTransaction]的方法
        /// 4. 注册AtTransactionAspect（Transient）
        ///    - AT事务切面，提供声明式事务支持
        /// 5. 注册AtTransactionTemplate（Transient）
        ///    - AT事务模板，提供编程式事务支持
        /// 6. 配置AtConfiguration选项（使用默认值）：
        ///    - ReportRetryCount = 5：上报重试5次
        ///    - ReportSuccessEnable = true：启用成功上报
        ///    - LockRetryInterval = 10ms：全局锁重试间隔
        ///    - LockRetryTimes = 30：全局锁重试次数
        ///    - TransactionTablePrefix = "undo_log"：undo_log表前缀
        ///
        /// 注册的服务说明：
        /// - DefaultAtTransactionManager：实现IAtTransactionManager，处理AT事务核心逻辑
        /// - DefaultAtDataSourceProxyFactory：创建AtDataSourceProxy，支持多数据源
        /// - AtTransactionInterceptor：AOP拦截器，自动开启和提交/回滚全局事务
        /// - AtTransactionAspect：基于特性的切面，简化事务声明
        /// - AtTransactionTemplate：类似Spring TransactionTemplate，编程式事务
        ///
        /// 调用时机：
        /// - 应用启动时在Startup.cs或Program.cs中调用
        /// - 在调用AddSeata()之后调用
        /// - 必须在添加数据源（AddAtDataSource）之前调用
        ///
        /// 使用示例：
        /// ```csharp
        /// // 最简单的配置（使用默认值）
        /// public void ConfigureServices(IServiceCollection services)
        /// {
        ///     services.AddSeata();              // 先注册Seata核心服务
        ///     services.AddAtMode();              // 注册AT模式服务
        ///     services.AddAtDataSource("...");   // 注册数据源
        /// }
        /// ```
        ///
        /// 注意事项：
        /// - 必须先调用AddSeata()注册核心服务
        /// - 配置使用默认值，适合快速启动和测试
        /// - 生产环境建议使用AddAtMode(Action<AtConfiguration>)自定义配置
        /// - 所有服务注册为Singleton，除了Aspect和Template（Transient）
        /// </summary>
        /// <param name="services">ASP.NET Core服务集合</param>
        /// <returns>服务集合，支持链式调用</returns>
        public static IServiceCollection AddAtMode(this IServiceCollection services)
        {
            // 注册AT事务管理器
            services.AddSingleton<IAtTransactionManager, DefaultAtTransactionManager>();

            // 注册AT数据源代理工厂
            services.AddSingleton<IAtDataSourceProxyFactory, DefaultAtDataSourceProxyFactory>();

            // 注册AT事务拦截器
            services.AddSingleton<IMethodInterceptor, AtTransactionInterceptor>();

            // 注册AT事务切面
            services.AddTransient<AtTransactionAspect>();

            // 注册AT事务模板
            services.AddTransient<AtTransactionTemplate>();

            // 注册AT配置
            services.Configure<AtConfiguration>(options =>
            {
                // 设置默认配置
                options.ReportRetryCount = 5;
                options.ReportSuccessEnable = true;
                options.LockRetryInterval = 10;
                options.LockRetryTimes = 30;
                options.TransactionTablePrefix = "undo_log";
            });

            return services;
        }

        /// <summary>
        /// 添加AT模式服务（自定义配置）
        ///
        /// 注册AT模式服务并允许自定义配置选项。
        ///
        /// 执行流程：
        /// 1. 调用AddAtMode()注册所有AT模式服务（使用默认配置）
        /// 2. 调用services.Configure(configure)应用自定义配置
        ///    - 自定义配置会覆盖默认配置
        /// 3. 返回服务集合
        ///
        /// 调用时机：
        /// - 应用启动时在Startup.cs或Program.cs中调用
        /// - 需要自定义AT配置时使用此方法
        /// - 生产环境推荐使用此方法
        ///
        /// 使用示例：
        /// ```csharp
        /// // 自定义配置
        /// services.AddAtMode(options =>
        /// {
        ///     options.ReportRetryCount = 10;              // 增加重试次数
        ///     options.LockRetryInterval = 20;             // 延长重试间隔
        ///     options.LockRetryTimes = 50;                // 增加锁重试次数
        ///     options.TransactionTablePrefix = "undo_log"; // 自定义表前缀
        ///     options.Serializer = "json";                 // 指定序列化方式
        /// });
        ///
        /// // 或者从配置文件加载
        /// services.AddAtMode(options =>
        /// {
        ///     Configuration.GetSection("Seata:At").Bind(options);
        /// });
        /// ```
        ///
        /// 配置选项说明：
        /// - ReportRetryCount：TC通信失败时的重试次数（默认5次）
        /// - ReportSuccessEnable：是否上报成功状态（默认true）
        /// - LockRetryInterval：获取全局锁失败后的重试间隔（默认10ms）
        /// - LockRetryTimes：获取全局锁的最大重试次数（默认30次）
        /// - TransactionTablePrefix：undo_log表前缀（默认"undo_log"）
        /// - Serializer：序列化方式（默认"json"）
        ///
        /// 注意事项：
        /// - configure委托会在默认配置之后执行，可以覆盖默认值
        /// - 配置修改后需要重启应用才能生效（非热更新）
        /// - LockRetryInterval * LockRetryTimes = 最大等待时间（默认300ms）
        /// - 合理设置重试参数以平衡性能和可靠性
        /// </summary>
        /// <param name="services">ASP.NET Core服务集合</param>
        /// <param name="configure">配置操作，用于自定义AtConfiguration</param>
        /// <returns>服务集合，支持链式调用</returns>
        public static IServiceCollection AddAtMode(this IServiceCollection services, Action<AtConfiguration> configure)
        {
            services.AddAtMode();
            services.Configure(configure);
            return services;
        }

        /// <summary>
        /// 添加AT模式数据源（单数据源）
        ///
        /// 注册默认的AT数据源代理，用于单数据源场景。
        ///
        /// 执行流程：
        /// 1. 注册IAtDataSourceProxy为Singleton服务
        /// 2. 使用工厂方法创建AtDataSourceProxy实例：
        ///    - 从DI容器获取IAtTransactionManager
        ///    - 从DI容器获取ILogger<AtDataSourceProxy>
        ///    - 从DI容器获取ILoggerFactory
        ///    - 创建AtDataSourceProxy并传入连接字符串和提供程序名
        /// 3. 返回服务集合
        ///
        /// 调用时机：
        /// - 在AddAtMode()之后调用
        /// - 单数据源场景使用此方法
        /// - 应用启动时在Startup.cs或Program.cs中调用
        ///
        /// 使用示例：
        /// ```csharp
        /// services.AddSeata();
        /// services.AddAtMode();
        /// services.AddAtDataSource(
        ///     connectionString: "Server=localhost;Database=mydb;User Id=sa;Password=***;",
        ///     providerName: "Microsoft.Data.SqlClient"
        /// );
        /// ```
        ///
        /// 支持的数据库：
        /// - SQL Server："Microsoft.Data.SqlClient"（默认，推荐）
        /// - MySQL："MySql.Data.MySqlClient"
        /// - PostgreSQL："Npgsql"
        /// - SQLite："Microsoft.Data.Sqlite"
        ///
        /// 注意事项：
        /// - 注册为Singleton，整个应用共享一个数据源代理实例
        /// - 连接字符串不应包含敏感信息（使用配置文件或环境变量）
        /// - 确保对应的数据库提供程序NuGet包已安装
        /// - 单数据源场景下，直接注入IAtDataSourceProxy使用
        /// </summary>
        /// <param name="services">ASP.NET Core服务集合</param>
        /// <param name="connectionString">数据库连接字符串</param>
        /// <param name="providerName">数据库提供程序名称，默认为SQL Server</param>
        /// <returns>服务集合，支持链式调用</returns>
        public static IServiceCollection AddAtDataSource(this IServiceCollection services,
            string connectionString,
            string providerName = "Microsoft.Data.SqlClient")
        {
            // 注册AT数据源代理
            services.AddSingleton<IAtDataSourceProxy>(provider =>
            {
                var transactionManager = provider.GetRequiredService<IAtTransactionManager>();
                var logger = provider.GetRequiredService<ILogger<AtDataSourceProxy>>();
                var loggerFactory = provider.GetRequiredService<ILoggerFactory>();

                return new AtDataSourceProxy(transactionManager, logger, loggerFactory, connectionString, providerName);
            });

            return services;
        }

        /// <summary>
        /// 添加AT模式数据源（命名数据源，多数据源）
        ///
        /// 注册命名的AT数据源代理，用于多数据源场景。
        ///
        /// 执行流程：
        /// 1. 注册IAtDataSourceProxy为Singleton服务
        /// 2. 使用工厂方法创建AtDataSourceProxy实例：
        ///    - 从DI容器获取依赖服务
        ///    - 创建AtDataSourceProxy并传入连接字符串和提供程序名
        ///    - 注意：name参数当前未使用，所有数据源注册为相同接口
        /// 3. 返回服务集合
        ///
        /// 调用时机：
        /// - 在AddAtMode()之后调用
        /// - 多数据源场景使用此方法
        /// - 每个数据源调用一次此方法
        ///
        /// 使用示例：
        /// ```csharp
        /// // 多数据源配置
        /// services.AddSeata();
        /// services.AddAtMode();
        ///
        /// // 主数据源
        /// services.AddAtDataSource(
        ///     name: "master",
        ///     connectionString: "Server=master-db;...",
        ///     providerName: "Microsoft.Data.SqlClient"
        /// );
        ///
        /// // 从数据源
        /// services.AddAtDataSource(
        ///     name: "slave",
        ///     connectionString: "Server=slave-db;...",
        ///     providerName: "Microsoft.Data.SqlClient"
        /// );
        ///
        /// // 使用工厂获取特定数据源
        /// var factory = serviceProvider.GetService<IAtDataSourceProxyFactory>();
        /// var masterDs = factory.Create("master", "...", "...");
        /// var slaveDs = factory.Create("slave", "...", "...");
        /// ```
        ///
        /// 多数据源使用建议：
        /// - 使用IAtDataSourceProxyFactory.Create(name, ...)获取特定数据源
        /// - 或者使用命名选项模式（IOptions<AtDataSourceOptions>）
        /// - 或者手动管理数据源字典
        ///
        /// 注意事项：
        /// - 当前实现name参数未实际使用，所有数据源注册为同一接口
        /// - 建议使用IAtDataSourceProxyFactory进行多数据源管理
        /// - 每次调用都会注册新的IAtDataSourceProxy实例
        /// - 多数据源场景下需要自行管理数据源选择逻辑
        /// </summary>
        /// <param name="services">ASP.NET Core服务集合</param>
        /// <param name="name">数据源名称，用于多数据源标识</param>
        /// <param name="connectionString">数据库连接字符串</param>
        /// <param name="providerName">数据库提供程序名称，默认为SQL Server</param>
        /// <returns>服务集合，支持链式调用</returns>
        public static IServiceCollection AddAtDataSource(this IServiceCollection services,
            string name,
            string connectionString,
            string providerName = "Microsoft.Data.SqlClient")
        {
            // 注册命名AT数据源代理
            services.AddSingleton<IAtDataSourceProxy>(provider =>
            {
                var transactionManager = provider.GetRequiredService<IAtTransactionManager>();
                var logger = provider.GetRequiredService<ILogger<AtDataSourceProxy>>();
                var loggerFactory = provider.GetRequiredService<ILoggerFactory>();

                return new AtDataSourceProxy(transactionManager, logger, loggerFactory, connectionString, providerName);
            });

            return services;
        }
    }

    /// <summary>
    /// AT模式配置选项
    ///
    /// 定义AT模式的各项配置参数，用于Options模式。
    ///
    /// 配置项说明：
    /// - ReportRetryCount：与TC通信失败时的重试次数
    /// - ReportSuccessEnable：是否上报成功状态给TC
    /// - LockRetryInterval：获取全局锁失败后的重试间隔（毫秒）
    /// - LockRetryTimes：获取全局锁的最大重试次数
    /// - TransactionTablePrefix：undo_log表名前缀
    /// - Serializer：序列化方式（json/protobuf）
    /// - LogEnable：是否启用日志
    /// - LogLevel：日志级别（INFO/DEBUG/WARN/ERROR）
    ///
    /// 使用场景：
    /// ```csharp
    /// // 方式1：代码配置
    /// services.AddAtMode(options =>
    /// {
    ///     options.ReportRetryCount = 10;
    ///     options.LockRetryTimes = 50;
    /// });
    ///
    /// // 方式2：配置文件
    /// // appsettings.json:
    /// {
    ///   "Seata": {
    ///     "At": {
    ///       "ReportRetryCount": 10,
    ///       "LockRetryInterval": 20,
    ///       "LockRetryTimes": 50,
    ///       "TransactionTablePrefix": "undo_log"
    ///     }
    ///   }
    /// }
    ///
    /// // Program.cs:
    /// services.AddAtMode(options =>
    /// {
    ///     Configuration.GetSection("Seata:At").Bind(options);
    /// });
    /// ```
    ///
    /// 性能调优建议：
    /// - ReportRetryCount：网络不稳定时增加（5-10），稳定网络可以减少（1-3）
    /// - LockRetryInterval：根据并发度调整，高并发增加间隔（20-50ms）
    /// - LockRetryTimes：根据业务超时要求，总等待时间 = Interval * Times
    ///
    /// 注意事项：
    /// - 配置修改需要重启应用才能生效
    /// - LockRetryInterval * LockRetryTimes 不宜超过业务超时时间
    /// - ReportSuccessEnable=false可以减少TC压力，但会失去状态跟踪
    /// </summary>
    public class AtConfiguration
    {
        /// <summary>
        /// 上报重试次数
        ///
        /// 向TC上报分支状态失败时的重试次数。
        ///
        /// 默认值：5
        /// 推荐值：
        /// - 稳定网络：1-3
        /// - 不稳定网络：5-10
        /// - 测试环境：1
        ///
        /// 注意事项：
        /// - 重试次数过多会延长事务完成时间
        /// - 重试失败会导致TC状态不一致（需要人工介入）
        /// - 设置为0表示不重试（不推荐）
        /// </summary>
        public int ReportRetryCount { get; set; } = 5;

        /// <summary>
        /// 是否上报成功状态
        ///
        /// 控制分支事务成功时是否向TC上报状态。
        ///
        /// 默认值：true
        ///
        /// true：上报成功状态，TC可以跟踪所有分支状态
        /// false：不上报成功状态，减少TC压力，仅上报失败状态
        ///
        /// 使用建议：
        /// - 生产环境：true（便于监控和问题排查）
        /// - 高性能场景：false（减少网络开销）
        /// - 测试环境：true（便于调试）
        ///
        /// 注意事项：
        /// - 设置为false会失去分支成功的可观测性
        /// - TC无法准确统计成功率
        /// </summary>
        public bool ReportSuccessEnable { get; set; } = true;

        /// <summary>
        /// 全局锁重试间隔（毫秒）
        ///
        /// 获取全局锁失败后，等待多久再次重试。
        ///
        /// 默认值：10ms
        /// 推荐值：
        /// - 低并发：5-10ms
        /// - 高并发：20-50ms
        /// - 测试环境：1ms
        ///
        /// 计算公式：
        /// 最大等待时间 = LockRetryInterval * LockRetryTimes
        /// 默认：10ms * 30 = 300ms
        ///
        /// 调优建议：
        /// - 并发度高时增加间隔，减少TC压力
        /// - 业务超时时间短时减少间隔
        /// - 间隔太小会导致CPU空转和网络拥塞
        ///
        /// 注意事项：
        /// - 间隔太短可能导致"锁风暴"
        /// - 间隔太长会增加事务响应时间
        /// - 建议使用指数退避策略（未实现）
        /// </summary>
        public int LockRetryInterval { get; set; } = 10;

        /// <summary>
        /// 全局锁重试次数
        ///
        /// 获取全局锁的最大重试次数，超过后抛出异常。
        ///
        /// 默认值：30
        /// 推荐值：
        /// - 快速失败：10-20
        /// - 正常业务：30-50
        /// - 长时间等待：100+
        ///
        /// 计算公式：
        /// 最大等待时间 = LockRetryInterval * LockRetryTimes
        /// 默认：10ms * 30 = 300ms
        ///
        /// 调优建议：
        /// - 根据业务超时要求设置
        /// - 不宜超过数据库事务超时时间
        /// - 结合LockRetryInterval一起调整
        ///
        /// 注意事项：
        /// - 重试耗尽会导致本地事务回滚
        /// - 全局事务也会回滚
        /// - 用户会收到"锁获取失败"异常
        /// </summary>
        public int LockRetryTimes { get; set; } = 30;

        /// <summary>
        /// 事务表前缀
        ///
        /// undo_log表的名称前缀，用于支持表名定制。
        ///
        /// 默认值："undo_log"
        ///
        /// 使用场景：
        /// - 多租户场景：每个租户使用不同的表前缀
        /// - 分库分表：不同库使用不同的表前缀
        /// - 测试环境：使用test_undo_log避免冲突
        ///
        /// 注意事项：
        /// - 修改后需要手动创建对应的表
        /// - 表结构必须与标准undo_log一致
        /// - 不同前缀的表互不影响
        /// </summary>
        public string TransactionTablePrefix { get; set; } = "undo_log";

        /// <summary>
        /// 序列化方式
        ///
        /// undo_log回滚信息的序列化格式。
        ///
        /// 默认值："json"
        /// 支持值：
        /// - "json"：JSON格式（默认，可读性好，便于调试）
        /// - "protobuf"：Protobuf格式（性能好，占用空间小）
        ///
        /// 性能对比：
        /// - JSON：序列化速度快，体积大，可读
        /// - Protobuf：序列化速度更快，体积小30-50%，不可读
        ///
        /// 使用建议：
        /// - 开发/测试环境：json
        /// - 生产环境：protobuf（性能要求高时）
        /// - 需要人工查看undo_log时：json
        ///
        /// 注意事项：
        /// - 修改序列化方式后，旧的undo_log无法反序列化
        /// - 不同实例必须使用相同的序列化方式
        /// </summary>
        public string Serializer { get; set; } = "json";

        /// <summary>
        /// 是否启用日志
        ///
        /// 控制AT模式是否输出详细日志。
        ///
        /// 默认值：true
        ///
        /// true：输出详细日志（分支注册、提交、回滚等）
        /// false：只输出错误日志
        ///
        /// 使用建议：
        /// - 开发环境：true
        /// - 生产环境：false（减少日志量）
        /// - 问题排查：true
        ///
        /// 注意事项：
        /// - 日志输出会影响性能（约5-10%）
        /// - 日志级别由LogLevel控制
        /// </summary>
        public bool LogEnable { get; set; } = true;

        /// <summary>
        /// 日志级别
        ///
        /// 控制日志输出的详细程度。
        ///
        /// 默认值："INFO"
        /// 支持值：
        /// - "DEBUG"：最详细，包含所有调试信息
        /// - "INFO"：正常信息（默认）
        /// - "WARN"：只输出警告
        /// - "ERROR"：只输出错误
        ///
        /// 使用建议：
        /// - 开发环境：DEBUG
        /// - 测试环境：INFO
        /// - 生产环境：WARN或ERROR
        /// - 问题排查：DEBUG
        ///
        /// 注意事项：
        /// - DEBUG级别会输出SQL、参数等敏感信息
        /// - 生产环境不建议使用DEBUG
        /// </summary>
        public string LogLevel { get; set; } = "INFO";
    }

    /// <summary>
    /// AT模式数据源代理工厂接口
    ///
    /// 定义创建和管理AtDataSourceProxy的工厂接口。
    ///
    /// 职责：
    /// - 创建AtDataSourceProxy实例
    /// - 缓存已创建的数据源代理（避免重复创建）
    /// - 支持单数据源和多数据源场景
    ///
    /// 使用场景：
    /// - 多数据源场景：根据name创建和获取不同的数据源
    /// - 动态数据源：运行时创建新的数据源代理
    /// - 数据源复用：缓存已创建的数据源，避免重复创建
    ///
    /// 实现类：
    /// - DefaultAtDataSourceProxyFactory：默认实现，使用ConcurrentDictionary缓存
    ///
    /// 注意事项：
    /// - 工厂注册为Singleton，整个应用共享
    /// - 创建的数据源代理会被缓存
    /// - 相同参数（connectionString + providerName）返回相同实例
    /// </summary>
    public interface IAtDataSourceProxyFactory
    {
        /// <summary>
        /// 创建数据源代理（单数据源）
        ///
        /// 根据连接字符串和提供程序名创建或获取缓存的数据源代理。
        ///
        /// 执行流程：
        /// 1. 使用providerName和connectionString生成缓存键
        /// 2. 检查缓存中是否已存在
        /// 3. 如果存在，返回缓存的实例
        /// 4. 如果不存在，创建新实例并缓存
        /// 5. 返回数据源代理
        ///
        /// 注意事项：
        /// - 相同参数会返回相同实例（单例模式）
        /// - 线程安全（使用ConcurrentDictionary）
        /// - 缓存键格式："{providerName}:{connectionString}"
        /// </summary>
        /// <param name="connectionString">数据库连接字符串</param>
        /// <param name="providerName">数据库提供程序名称，默认为SQL Server</param>
        /// <returns>AT数据源代理实例</returns>
        IAtDataSourceProxy Create(string connectionString, string providerName = "Microsoft.Data.SqlClient");

        /// <summary>
        /// 创建数据源代理（多数据源）
        ///
        /// 根据名称创建或获取缓存的数据源代理，用于多数据源场景。
        ///
        /// 执行流程：
        /// 1. 使用name作为缓存键
        /// 2. 检查缓存中是否已存在
        /// 3. 如果存在，返回缓存的实例
        /// 4. 如果不存在，创建新实例并缓存
        /// 5. 返回数据源代理
        ///
        /// 使用示例：
        /// ```csharp
        /// var factory = serviceProvider.GetService<IAtDataSourceProxyFactory>();
        ///
        /// // 创建主库数据源
        /// var masterDs = factory.Create("master", "Server=master-db;...", "Microsoft.Data.SqlClient");
        ///
        /// // 创建从库数据源
        /// var slaveDs = factory.Create("slave", "Server=slave-db;...", "Microsoft.Data.SqlClient");
        /// ```
        ///
        /// 注意事项：
        /// - name必须唯一，相同name返回相同实例
        /// - 线程安全（使用ConcurrentDictionary）
        /// - 缓存键就是name本身
        /// </summary>
        /// <param name="name">数据源名称，用于标识和缓存</param>
        /// <param name="connectionString">数据库连接字符串</param>
        /// <param name="providerName">数据库提供程序名称，默认为SQL Server</param>
        /// <returns>AT数据源代理实例</returns>
        IAtDataSourceProxy Create(string name, string connectionString, string providerName = "Microsoft.Data.SqlClient");
    }

    /// <summary>
    /// AT模式数据源代理工厂默认实现
    ///
    /// 实现IAtDataSourceProxyFactory接口，使用ConcurrentDictionary缓存数据源代理。
    ///
    /// 职责：
    /// 1. 创建AtDataSourceProxy实例
    /// 2. 缓存已创建的数据源代理
    /// 3. 确保线程安全
    /// 4. 避免重复创建相同配置的数据源
    ///
    /// 工作原理：
    /// - 使用ConcurrentDictionary<string, IAtDataSourceProxy>缓存
    /// - 键：connectionString+providerName或name
    /// - 值：AtDataSourceProxy实例
    /// - GetOrAdd保证线程安全和幂等性
    ///
    /// 缓存策略：
    /// - 单数据源：键={providerName}:{connectionString}
    /// - 多数据源：键=name
    /// - 永久缓存，不会过期
    /// - 应用重启后缓存清空
    ///
    /// 线程安全：
    /// - ConcurrentDictionary是线程安全的
    /// - GetOrAdd方法保证只创建一次
    /// - 多线程并发调用安全
    ///
    /// 性能特点：
    /// - 首次创建较慢（需要反射加载提供程序）
    /// - 后续获取很快（直接从缓存返回）
    /// - 内存占用：每个数据源约1KB
    ///
    /// 注意事项：
    /// - 工厂本身注册为Singleton
    /// - 创建的数据源代理也是单例的（通过缓存实现）
    /// - 不支持数据源热更新（需要重启应用）
    /// </summary>
    public class DefaultAtDataSourceProxyFactory : IAtDataSourceProxyFactory
    {
        private readonly IAtTransactionManager _transactionManager;
        private readonly ILogger<AtDataSourceProxy> _logger;
        private readonly ILoggerFactory _loggerFactory;
        private readonly ConcurrentDictionary<string, IAtDataSourceProxy> _dataSourceProxies;

        /// <summary>
        /// 构造函数
        ///
        /// 初始化工厂，注入依赖服务。
        ///
        /// 依赖服务：
        /// - IAtTransactionManager：用于创建数据源代理时传入
        /// - ILogger<AtDataSourceProxy>：用于数据源代理的日志记录
        /// - ILoggerFactory：用于创建子组件的logger
        ///
        /// 注意事项：
        /// - 通过依赖注入获取这些服务
        /// - 所有数据源代理共享同一个事务管理器
        /// - 缓存字典在构造时初始化
        /// </summary>
        /// <param name="transactionManager">AT事务管理器</param>
        /// <param name="logger">AtDataSourceProxy专用logger</param>
        /// <param name="loggerFactory">日志工厂</param>
        public DefaultAtDataSourceProxyFactory(
            IAtTransactionManager transactionManager,
            ILogger<AtDataSourceProxy> logger,
            ILoggerFactory loggerFactory)
        {
            _transactionManager = transactionManager;
            _logger = logger;
            _loggerFactory = loggerFactory;
            _dataSourceProxies = new ConcurrentDictionary<string, IAtDataSourceProxy>();
        }

        /// <summary>
        /// 创建或获取单数据源代理
        ///
        /// 使用连接字符串和提供程序名作为缓存键，确保相同配置返回同一实例。
        ///
        /// 执行流程：
        /// 1. 生成缓存键：key = "{providerName}:{connectionString}"
        /// 2. 调用_dataSourceProxies.GetOrAdd()：
        ///    - 如果缓存中存在，直接返回
        ///    - 如果不存在，执行工厂方法创建新实例
        /// 3. 创建新实例时：
        ///    - 使用new AtDataSourceProxy(...)
        ///    - 传入_transactionManager、_logger、_loggerFactory
        ///    - 传入connectionString和providerName
        /// 4. 返回数据源代理实例
        ///
        /// 缓存键示例：
        /// - "Microsoft.Data.SqlClient:Server=localhost;Database=mydb;..."
        /// - "MySql.Data.MySqlClient:Server=127.0.0.1;Database=testdb;..."
        ///
        /// 注意事项：
        /// - 缓存键包含完整连接字符串，确保唯一性
        /// - 连接字符串的任何差异都会创建新实例
        /// - 线程安全，并发调用安全
        /// </summary>
        /// <param name="connectionString">数据库连接字符串</param>
        /// <param name="providerName">数据库提供程序名称</param>
        /// <returns>AT数据源代理实例（可能是缓存的）</returns>
        public IAtDataSourceProxy Create(string connectionString, string providerName = "Microsoft.Data.SqlClient")
        {
            var key = $"{providerName}:{connectionString}";

            return _dataSourceProxies.GetOrAdd(key, _ =>
                new AtDataSourceProxy(_transactionManager, _logger, _loggerFactory, connectionString, providerName));
        }

        /// <summary>
        /// 创建或获取命名数据源代理
        ///
        /// 使用名称作为缓存键，用于多数据源场景。
        ///
        /// 执行流程：
        /// 1. 使用name作为缓存键
        /// 2. 调用_dataSourceProxies.GetOrAdd()：
        ///    - 如果缓存中存在该name，直接返回
        ///    - 如果不存在，执行工厂方法创建新实例
        /// 3. 创建新实例时：
        ///    - 使用new AtDataSourceProxy(...)
        ///    - 传入所有依赖服务和配置参数
        /// 4. 返回数据源代理实例
        ///
        /// 使用示例：
        /// ```csharp
        /// var factory = new DefaultAtDataSourceProxyFactory(...);
        ///
        /// // 第一次调用，创建新实例
        /// var ds1 = factory.Create("master", "Server=...", "Microsoft.Data.SqlClient");
        ///
        /// // 第二次调用，返回缓存的实例
        /// var ds2 = factory.Create("master", "Server=...", "Microsoft.Data.SqlClient");
        ///
        /// Assert.Same(ds1, ds2); // 引用相同
        /// ```
        ///
        /// 注意事项：
        /// - name必须唯一，作为数据源的标识符
        /// - 相同name无论参数如何都返回首次创建的实例
        /// - 建议name使用有意义的命名（如"master"、"slave"、"order-db"）
        /// - 线程安全，并发调用安全
        /// </summary>
        /// <param name="name">数据源名称，用于标识和缓存</param>
        /// <param name="connectionString">数据库连接字符串</param>
        /// <param name="providerName">数据库提供程序名称</param>
        /// <returns>AT数据源代理实例（可能是缓存的）</returns>
        public IAtDataSourceProxy Create(string name, string connectionString, string providerName = "Microsoft.Data.SqlClient")
        {
            return _dataSourceProxies.GetOrAdd(name, _ =>
                new AtDataSourceProxy(_transactionManager, _logger, _loggerFactory, connectionString, providerName));
        }
    }
}